/// author stevenHu
///
/// created by hujintao
/// created at 2021/12/20

// ignore_for_file: constant_identifier_names
enum DateFormat {
  DEFAULT, //yyyy-MM-dd HH:mm:ss.SSS
  NORMAL, //yyyy-MM-dd HH:mm:ss
  YEAR_MONTH_DAY_HOUR_MINUTE, //yyyy-MM-dd HH:mm
  YEAR_MONTH_DAY, //yyyy-MM-dd
  YEAR_MONTH, //yyyy-MM
  MONTH_DAY, //MM-dd
  MONTH_DAY_HOUR_MINUTE, //MM-dd HH:mm
  HOUR_MINUTE_SECOND, //HH:mm:ss
  HOUR_MINUTE, //HH:mm
}

class DateUtil {
  static const num ONE_MINUTE = 60000;
  static const num ONE_HOUR = 3600000;
  static const num ONE_DAY = 86400000;
  static const num ONE_WEEK = 604800000;

  static const String ONE_MINUTE_AGO = "分钟前";
  static const String ONE_HOUR_AGO = "小时前";
  static const String ONE_DAY_AGO = "天前";
  static const String ONE_WEEK_AGO = "周前";
  static const String ONE_MONTH_AGO = "月前";
  static const String ONE_YEAR_AGO = "年前";

  /// 格式化
  static String format(DateTime date) {
    num delta =
        DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch;

    /// 刚刚
    if (delta < 1 * ONE_MINUTE) {
      return '刚刚';
    }

    // 分钟前
    if (delta < ONE_HOUR) {
      num minutes = toMinutes(delta);
      return (minutes <= 0 ? 1 : minutes).toInt().toString() + ONE_MINUTE_AGO;
    }

    // 小时前
    if (delta < 24 * ONE_HOUR) {
      num hours = toHours(delta);
      return (hours <= 0 ? 1 : hours).toInt().toString() + ONE_HOUR_AGO;
    }

    // 几天前
    if (delta < 7 * ONE_DAY) {
      num days = toDays(delta);
      return (days <= 0 ? 1 : days).toInt().toString() + ONE_DAY_AGO;
    }

    // 几周前
    if (delta < 30 * ONE_DAY) {
      num days = toDays(delta) ~/ 7; //相除取整
      return (days <= 0 ? 1 : days).toInt().toString() + ONE_WEEK_AGO;
    }

    // 几月前
    if (delta < 365 * ONE_DAY) {
      num days = toMonths(delta); //相除取整
      return (days <= 0 ? 1 : days).toInt().toString() + ONE_MONTH_AGO;
    }

    return '${date.year}/${date.month.toString().padLeft(2, '0')}/${date.day.toString().padLeft(2, '0')}';
  }

  /// 时间字符串分割成数组，格式：2022-12-10:55:21
  /*
  DateTime(
    DateUtil.analysis(item.expired_at)[0],
    DateUtil.analysis(item.expired_at)[1],
    DateUtil.analysis(item.expired_at)[2],
    DateUtil.analysis(item.expired_at)[3],
    DateUtil.analysis(item.expired_at)[4],
    DateUtil.analysis(item.expired_at)[5]).difference(DateTime.now()).inMinutes
  */
  List analysis(time) {
    String time1 = time.replaceAll(':', '-');
    List list = time1.replaceAll(' ', '-').split('-');
    return list.map((element) => int.parse(element)).toList();
  }

  /// 星期字符串
  static String weekdayToString(int weekday) {
    return ['', '周一', '周二', '周三', '周四', '周五', '周六', '周日'][weekday];
  }

  // 时间戳字符串 yyyy-MM-dd HH:mm:ss
  static String currentTimeStamp() {
    DateTime now = DateTime.now();
    String nowString =
        DateUtil.formatMessageDateTime(now.toString(), DateFormat.NORMAL);
    return nowString;
  }

  //消息时间显示
  static String calculateMessageTime(int timestamp) {
    if (timestamp == 0) {
      return '';
    }
    DateTime now = DateTime.now();
    String nowString = DateUtil.formatMessageDateTime(
        now.toString(), DateFormat.YEAR_MONTH_DAY);

    DateTime lastDay = now.subtract(const Duration(days: 1));
    String lastDayString = DateUtil.formatMessageDateTime(
        lastDay.toString(), DateFormat.YEAR_MONTH_DAY);

    DateTime time = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
    String timeString = DateUtil.formatMessageDateTime(
        time.toString(), DateFormat.YEAR_MONTH_DAY);

    String morningOrAfternoon = time.hour < 12 ? '上午' : '下午';

    int timeHours = time.hour > 12 ? time.hour - 12 : time.hour;
    String result =
        '$morningOrAfternoon $timeHours:${time.minute.toString().padLeft(2, '0')}';

    if (timeString == nowString) {
      return result;
    } else if (timeString == lastDayString) {
      return '昨天 $result';
    } else if (now.difference(time).inDays < 7) {
      return '${weekdayToString(time.weekday)} $result';
    } else {
      return '${time.year}年${time.month}月${time.day}日 $result';
    }
  }

  static String formatMessageDateTime(
    String time,
    DateFormat format, {
    String dateSeparate = "",
    String timeSeparate = "",
  }) {
    switch (format) {
      case DateFormat.NORMAL: //yyyy-MM-dd HH:mm:ss
        time = time.substring(0, "yyyy-MM-dd HH:mm:ss".length);
        break;
      case DateFormat.YEAR_MONTH_DAY_HOUR_MINUTE: //yyyy-MM-dd HH:mm
        time = time.substring(0, "yyyy-MM-dd HH:mm".length);
        break;
      case DateFormat.YEAR_MONTH_DAY: //yyyy-MM-dd
        time = time.substring(0, "yyyy-MM-dd".length);
        break;
      case DateFormat.YEAR_MONTH: //yyyy-MM
        time = time.substring(0, "yyyy-MM".length);
        break;
      case DateFormat.MONTH_DAY: //MM-dd
        time = time.substring("yyyy-".length, "yyyy-MM-dd".length);
        break;
      case DateFormat.MONTH_DAY_HOUR_MINUTE: //MM-dd HH:mm
        time = time.substring("yyyy-".length, "yyyy-MM-dd HH:mm".length);
        break;
      case DateFormat.HOUR_MINUTE_SECOND: //HH:mm:ss
        time =
            time.substring("yyyy-MM-dd ".length, "yyyy-MM-dd HH:mm:ss".length);
        break;
      case DateFormat.HOUR_MINUTE: //HH:mm
        time = time.substring("yyyy-MM-dd ".length, "yyyy-MM-dd HH:mm".length);
        break;
      default:
        break;
    }
    time = dateTimeSeparate(time, dateSeparate, timeSeparate);
    return time;
  }

  /// date Time Separate.
  static String dateTimeSeparate(
      String time, String dateSeparate, String timeSeparate) {
    if (dateSeparate.isNotEmpty) {
      time = time.replaceAll("-", dateSeparate);
    }
    if (timeSeparate.isNotEmpty) {
      time = time.replaceAll(":", timeSeparate);
    }
    return time;
  }

  /// 是否是当天.
  static bool isToday(int milliseconds, {bool isUtc = false}) {
    if (milliseconds == 0) {
      return false;
    }
    DateTime old =
        DateTime.fromMillisecondsSinceEpoch(milliseconds, isUtc: isUtc);
    DateTime now = isUtc ? DateTime.now().toUtc() : DateTime.now().toLocal();
    return old.year == now.year && old.month == now.month && old.day == now.day;
  }

  /// 是否是昨天.
  static bool isYesterday(DateTime dateTime, DateTime locDateTime) {
    if (yearIsEqual(dateTime, locDateTime)) {
      int spDay = getDayOfYear(locDateTime) - getDayOfYear(dateTime);
      return spDay == 1;
    } else {
      return ((locDateTime.year - dateTime.year == 1) &&
          dateTime.month == 12 &&
          locDateTime.month == 1 &&
          dateTime.day == 31 &&
          locDateTime.day == 1);
    }
  }

  /// 是否同年.
  static bool yearIsEqual(DateTime dateTime, DateTime locDateTime) {
    return dateTime.year == locDateTime.year;
  }

  /// 在今年的第几天.
  static int getDayOfYear(DateTime dateTime) {
    /// month->days.
    Map<int, int> MONTHDAY = {
      1: 31,
      2: 28,
      3: 31,
      4: 30,
      5: 31,
      6: 30,
      7: 31,
      8: 31,
      9: 30,
      10: 31,
      11: 30,
      12: 31,
    };
    int year = dateTime.year;
    int month = dateTime.month;
    int days = dateTime.day;
    if (MONTHDAY.isNotEmpty) {
      for (int i = 1; i < month; i++) {
        days = days + int.parse(MONTHDAY[i].toString());
      }
    }

    if (isLeapYearByYear(year) && month > 2) {
      days = days + 1;
    }
    return days;
  }

  /// 返回是否为闰年。
  static bool isLeapYearByYear(int year) {
    return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
  }

  /// 读取时间戳 * 1000
  static num timestamp(int timestamp) {
    if (timestamp <= 0) {
      return 0;
    }
    var date = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
    num delta =
        DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch;
    return delta;
  }

  /// 当前时间戳 ! * 10000
  static int currentTimeMillis() {
    return DateTime.now().millisecondsSinceEpoch;
  }

  /// 展示时间
  static String displayTime(int timestamp) {
    if (timestamp == 0) {
      return '';
    }
    var date = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
    var time = '';
    time = DateUtil.format(date);
    return time;
  }

  /// 读取时间戳
  static String readTimestamp(int timestamp) {
    if (timestamp.bitLength > 0 || timestamp == 0) {
      return '';
    }

    DateTime now = DateTime.now();
    DateTime date = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);

    Duration diff = now.difference(date);
    int mins = diff.inMinutes;
    int hours = diff.inHours;
    int days = diff.inDays;

    if (mins == 0) {
      return '刚刚';
    } else if (mins < 60) {
      return '$mins分钟前';
    } else if (hours < 24) {
      return '$hours小时前';
    } else if (days < 30) {
      return '$days天前';
    } else if (days < 365) {
      return '${days ~/ 30}月前';
    } else if (days > 365) {
      return '${days ~/ 365}年前';
    } else {
      return '';
    }
  }

  /// 返回星期几字符串
  static weekDay(String weekDay) {
    switch (weekDay) {
      case '1':
        return '星期一';
      case '2':
        return '星期二';
      case '3':
        return '星期三';
      case '4':
        return '星期四';
      case '5':
        return '星期五';
      case '6':
        return '星期六';
      case '7':
        return '星期日';
      default:
        return '星期一';
    }
  }

  /// 当前时间字符串
  static currentTime() {
    var now = DateTime.now();
    var a = now.millisecondsSinceEpoch;
    return DateTime.fromMillisecondsSinceEpoch(a).toString();
  }

  static getDateString(int timestamp) {
    DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp);
    return '${dateTime.year}-${dateTime.month}-${dateTime.day}';
  }

  /// 时间戳转换小时
  static int currentMinutes(int timestamp) {
    if (timestamp == null) {
      return 0;
    }
    var date = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
    int delta =
        DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch;

    int minute = int.parse(DateUtil.toMinutes(delta).toString());
    print("minutes${minute}");
    return minute;
  }

  /// 时间戳转换秒
  static num toSeconds(num date) {
    return date / 1000;
  }

  /// 时间戳转换分钟
  static num toMinutes(num date) {
    return toSeconds(date) / 60;
  }

  /// 时间戳转换小时
  static num toHours(num date) {
    return toMinutes(date) / 60;
  }

  /// 时间戳转换天
  static num toDays(num date) {
    return toHours(date) / 24;
  }

  /// 时间戳转换月
  static num toMonths(num date) {
    return toDays(date) / 30;
  }

  /// 时间戳转换年
  static num toYears(num date) {
    return toMonths(date) / 12;
  }
}
